package com.puzzlebazar.client.heyawake;

import com.puzzlebazar.client.puzzle.model.MoveClearPuzzle;
import com.puzzlebazar.client.puzzle.model.MoveVisitorImpl;
import com.puzzlebazar.client.squaregrid.model.MoveChangeState;
import com.puzzlebazar.client.squaregrid.model.MoveClearStates;
import com.puzzlebazar.client.squaregrid.view.DrawableUtils;
import com.puzzlebazar.client.squaregrid.view.FillDrawable;
import com.puzzlebazar.client.squaregrid.view.ImageDrawable;
import com.puzzlebazar.client.squaregrid.view.StringDrawable;
import com.puzzlebazar.client.squaregrid.view.DrawableLayer;
import com.puzzlebazar.client.util.Recti;
import com.puzzlebazar.client.util.Vec2i;

public class DrawMoveVisitor extends MoveVisitorImpl implements HeyawakeMoveVisitor {

	private final DrawableLayer gridLayer;
	private final DrawableLayer cellLayer;
	private final DrawableLayer stringLayer;

	/**
	 * Creates a visitor for drawing the content of the passed moves
	 * 
	 * @param cellLayer The cell layer to draw cells in
	 * @param gridLayer The grid layer to draw large grids
	 * @param stringLayer The string layer to draw numbers
	 */
	public DrawMoveVisitor(
			DrawableLayer cellLayer,
			DrawableLayer gridLayer,
			DrawableLayer stringLayer) {
		this.cellLayer = cellLayer;
		this.gridLayer = gridLayer;
		this.stringLayer = stringLayer;
	}
	
	@Override
	public void visitAddRoomMove(MoveAddRoom move) throws Exception {
		Recti roomArea = move.getRoomArea();

		DrawableUtils.addEdgeRectangle(roomArea, gridLayer, "gridLine", null, 5);
		
		stringLayer.addDrawable( new StringDrawable(
				new Vec2i(roomArea.x, roomArea.y), 
				"gridNumber",
				null, 
				valueToString(move.getValue()) ) );			
	}

	/**
	 * Converts a room value to the corresponding string
	 * 
	 * @param value The room value
	 * @return The corresponding string
	 */
	private String valueToString( int value ) {
		if( value < 0 ) return "";
		return Integer.toString(value);
	}
	
	@Override
	public void visitRemoveRoomMove(MoveRemoveRoom move) {
		try{
			Recti roomArea = move.getRoomArea();

			DrawableUtils.removeEdgeRectangle(roomArea, gridLayer, null);
			
			stringLayer.removeCellDrawable( new Vec2i(roomArea.x, roomArea.y), null );
		}
		catch( Exception exception ) {
			exception.printStackTrace();
		}		
	}

	@Override
	public void visitChangeStateMove(MoveChangeState move) {
		try{
			final int stateBefore = move.getStateBefore();
			final int stateAfter  = move.getStateAfter();
			final Vec2i loc = move.getLoc();
			
			if( stateBefore == stateAfter )
				return;
			
			if( stateBefore == HeyawakeModel.States.FILLED || stateBefore == HeyawakeModel.States.KNOWN_EMPTY )
				cellLayer.removeCellDrawable( loc, null );
			if( stateAfter != HeyawakeModel.States.EMPTY ) {
				switch ( stateAfter ) {
				case HeyawakeModel.States.FILLED:
					cellLayer.addDrawable( new FillDrawable(loc, null, "blackfill") );
					break;
				case HeyawakeModel.States.KNOWN_EMPTY:
					cellLayer.addDrawable( new ImageDrawable(loc, null, "circle.png") );
					break;
				default:
					throw new Exception( "Unknown Heyawake state" );	
				}
			}			
		}
		catch( Exception exception ) {
			exception.printStackTrace();
		}		
	}


	@Override
	public void visitClearStateMove(MoveClearStates clearStateMove) throws Exception {
		cellLayer.clear();
	}


	@Override
	public void visitMoveClearPuzzle(MoveClearPuzzle move) throws Exception {
		cellLayer.clear();
		gridLayer.clear();
		stringLayer.clear();
	}


}
